package com.zhitan.netty.util;

import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufUtil;
import lombok.extern.slf4j.Slf4j;

import java.math.BigInteger;
import java.nio.ByteBuffer;

import static org.springframework.util.StringUtils.isEmpty;

@Slf4j
public class HexHandleUtil {

    /**
     * 截取byte[]
     *
     * @param src   源数据
     * @param begin 开始位置
     * @param count 取值数量
     * @return 截取后的byte[]
     */
    public static byte[] subBytes(byte[] src, int begin, int count) {
        byte[] bs = new byte[count];
        for (int i = begin; i < begin + count; i++) {
            bs[i - begin] = src[i];
        }
        return bs;
    }

    /**
     * byte 数组转byteBuffer
     *
     * @param byteArray 字节数组
     */
    public static ByteBuffer byte2Bytebuffer(byte[] byteArray) {

        // 初始化一个和byte长度一样的buffer
        ByteBuffer buffer = ByteBuffer.allocate(byteArray.length);
        // 数组放到buffer中
        buffer.put(byteArray);
        // 重置 limit 和 position 值 否则 buffer 读取数据不对
        buffer.flip();
        return buffer;
    }

    /**
     * byteBuffer 转 byte数组
     *
     * @param buffer ByteBuffer数据
     * @return byte数组
     */
    public static byte[] bytebuffer2ByteArray(ByteBuffer buffer) {
        // 重置 limit 和 position 值
        buffer.flip();
        // 获取buffer中有效大小
        int len = buffer.limit() - buffer.position();

        byte[] bytes = new byte[len];

        for (int i = 0; i < bytes.length; i++) {
            bytes[i] = buffer.get();
        }

        return bytes;
    }


    /**
     * 字节数组转为16进制数据（大端）
     *
     * @param bytes 字节数组
     * @return 16进制数据
     */
    public static String bytesToBigHex(byte[] bytes) {
        String strHex = "";
        StringBuilder sb = new StringBuilder("");
        for (int n = bytes.length - 1; n >= 0; n--) {
            strHex = Integer.toHexString(bytes[n] & 0xFF);
            // 每个字节由两个字符表示，位数不够，高位补0
            sb.append((strHex.length() == 1) ? "0" + strHex : strHex);
        }
        return sb.toString().trim();
    }

    /**
     * byte数组转16进制字符串（小端）
     *
     * @param bytes byte数组
     * @return 字符串
     */
    public static String bytesToLittleHex(byte[] bytes) {
        StringBuilder sb = new StringBuilder();
        if (!isEmpty(bytes)) {
            for (int i = 0; i < bytes.length; i++) {
                sb.append(String.format("%02X", bytes[i]));
            }
        }
        return sb.toString();
    }

    /**
     * 去除需要校验的数据为
     *
     * @param buf        bug
     * @param dataLength 数据长度
     * @return 取值数据
     */
    public static byte[] byteBufToBytes(ByteBuf buf, Integer dataLength) {
        // 创建字节数组
        byte[] b = ByteBufUtil.getBytes(buf);
        return subBytes(b, 2, dataLength);
    }


    /**
     * 将byte[]转为各种进制的字符串
     *
     * @param bytes byte[]
     * @param radix 基数可以转换进制的范围，从Character.MIN_RADIX到Character.MAX_RADIX，超出范围后变为10进制
     * @return 转换后的字符串
     */
    public static String binary(byte[] bytes, int radix) {
        // 这里的1代表正数
        return new BigInteger(1, bytes).toString(radix);
    }

    /**
     * 16进制转换10进制
     *
     * @param hex 16进制字符串
     * @return 10进制
     */
    public static int hex2decimal(String hex) {
        return Integer.parseInt(hex, 16);
    }

    /**
     * int到byte[] 由高位到低位
     *
     * @param i 需要转换为byte数组的整行值。
     * @return byte数组
     */
    public static byte[] intToByteArray(int i) {
        byte[] result = new byte[4];
        result[0] = (byte) ((i >> 24) & 0xFF);
        result[1] = (byte) ((i >> 16) & 0xFF);
        result[2] = (byte) ((i >> 8) & 0xFF);
        result[3] = (byte) (i & 0xFF);
        return result;
    }

    /**
     * byte[]转int
     *
     * @param bytes 需要转换成int的数组
     * @return int值
     */
    public static int byteArrayToInt(byte[] bytes) {
        int value = 0;
        for (int i = 0; i < 4; i++) {
            int shift = (3 - i) * 8;
            value += (bytes[i] & 0xFF) << shift;
        }
        return value;
    }


    /**
     * long类型转成byte数组
     */
    public static byte[] longToBytes(long number) {
        long temp = number;
        byte[] b = new byte[8];
        for (int i = 0; i < b.length; i++) {
            // 将最低位保存在最低位
            b[i] = new Long(temp & 0xff).byteValue();
            temp = temp >> 8;
        }
        return b;
    }

    /**
     * byte[] 转 long类型
     * 8位
     *
     * @param b 字节数组
     * @return long类型
     */
    public static long bytesToLong(byte[] b) {
        long s = 0;
        //最低位
        long s0 = b[0] & 0xff;
        long s1 = b[1] & 0xff;
        long s2 = b[2] & 0xff;
        long s3 = b[3] & 0xff;
        //最低位
        long s4 = b[4] & 0xff;
        long s5 = b[5] & 0xff;
        long s6 = b[6] & 0xff;
        long s7 = b[7] & 0xff;
        //s0不变
        s1 <<= 8;
        s2 <<= 16;
        s3 <<= 24;
        s4 <<= 8 * 4;
        s5 <<= 8 * 5;
        s6 <<= 8 * 6;
        s7 <<= 8 * 7;
        s = s0 | s1 | s2 | s3 | s4 | s5 | s6 | s7;
        return s;
    }

}


